package com.example.admin.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.admin.dto.*;
import com.example.admin.mapper.GoodsMapper;
import com.example.admin.po.GoodsDetailPO;
import com.example.admin.service.GoodsService;
import com.example.admin.vo.*;
import com.example.common.bo.PageParamBO;
import com.example.common.exception.ServiceException;
import com.example.common.mapper.GoodsAttrMapper;
import com.example.common.mapper.GoodsAttrValueMapper;
import com.example.common.po.GoodsAttrPO;
import com.example.common.po.GoodsAttrValuePO;
import com.example.common.po.GoodsPO;
import com.example.common.po.GoodsSpecPO;
import com.example.common.service.GoodsAttrService;
import com.example.common.service.GoodsAttrValueService;
import com.example.common.service.GoodsSpecService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 商品
 */
@Service("adminGoodsServiceImpl")
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, GoodsPO>
        implements GoodsService {
    @Autowired
    private HttpServletRequest httpServletRequest;

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private GoodsAttrMapper goodsAttrMapper;

    @Autowired
    private GoodsAttrValueMapper goodsAttrValueMapper;

    @Autowired
    private GoodsAttrService goodsAttrService;

    @Autowired
    private GoodsAttrValueService goodsAttrValueService;

    @Autowired
    private GoodsSpecService goodsSpecService;

    @Resource
    DataSourceTransactionManager dataSourceTransactionManager;

    @Resource
    TransactionDefinition transactionDefinition;

    /**
     * 分页
     *
     * @param pageParamBO
     * @param goodsPaginateDTO
     * @return
     */
    @Override
    public IPage getPaginate(PageParamBO pageParamBO, GoodsPaginateDTO goodsPaginateDTO) {
        // 查询数据
        QueryWrapper queryWrapper = new QueryWrapper<GoodsPO>().select("goods_id", "goods_name", "goods_cover", "sort", "is_hot", "is_new", "is_show")
                .orderByAsc("sort")
                .orderByDesc("goods_id");
        if (!Objects.isNull(goodsPaginateDTO.getCatId()) && goodsPaginateDTO.getCatId() != 0) {
            queryWrapper.eq("cat_id", goodsPaginateDTO.getCatId());
        }
        if (!Objects.isNull(goodsPaginateDTO.getGoodsName()) && !goodsPaginateDTO.getGoodsName().isEmpty()) {
            queryWrapper.like("goods_name", goodsPaginateDTO.getGoodsName());
        }
        return goodsMapper.selectPage(
                new Page<>(pageParamBO.getPageIndex(), pageParamBO.getPageSize()),
                queryWrapper
        ).convert(po -> {
            GoodsPaginateVO vo = new GoodsPaginateVO();
            BeanUtils.copyProperties(po, vo);
            return vo;
        });
    }

    /**
     * 添加商品
     *
     * @param goodsAddDto
     * @return
     */
    @Override
    public Boolean add(GoodsAddDTO goodsAddDto) {
        if (goodsAddDto.getSpec().size() == 0) {
            throw new ServiceException("最少填写一个规格", 104);
        }
        //开启事务
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        try {
            // 将商品添加到数据库中
            GoodsPO insert = new GoodsPO();
            BeanUtils.copyProperties(goodsAddDto, insert);
            if (!Objects.isNull(goodsAddDto.getGoodsGallery())) {
                insert.setGoodsGallery(JSONObject.toJSONString(goodsAddDto.getGoodsGallery()));
            }
            goodsMapper.insert(insert);
            if (goodsAddDto.getSpecType()) {
                // 添加属性
                List<GoodsAttrPO> goodsAttrPOList = new ArrayList<>();
                for (GoodsAddAttrDTO d : goodsAddDto.getAttr()) {
                    GoodsAttrPO in = new GoodsAttrPO();
                    BeanUtils.copyProperties(d, in);
                    in.setGoodsId(insert.getGoodsId());
                    goodsAttrPOList.add(in);
                }
                goodsAttrService.saveBatch(goodsAttrPOList);
                //添加属性值
                List<GoodsAttrValuePO> goodsAttrValuePOList = new ArrayList<>();
                for (int i = 0; i < goodsAddDto.getAttr().size(); i++) {
                    GoodsAddAttrDTO attrDto = goodsAddDto.getAttr().get(i);
                    GoodsAttrPO data = goodsAttrPOList.get(i);
                    for (GoodsAddAttrValueDTO d : attrDto.getAttrValues()) {
                        GoodsAttrValuePO in = new GoodsAttrValuePO();
                        BeanUtils.copyProperties(d, in);
                        in.setGoodsId(insert.getGoodsId());
                        in.setAttrId(data.getAttrId());
                        goodsAttrValuePOList.add(in);
                    }
                }
                // 插入属性值
                goodsAttrValueService.saveBatch(goodsAttrValuePOList);
            }
            // 添加规格组合
            List<GoodsSpecPO> goodsSpecPOList = new ArrayList<>();
            for (GoodsAddSpecDTO d : goodsAddDto.getSpec()) {
                GoodsSpecPO in = new GoodsSpecPO();
                BeanUtils.copyProperties(d, in);
                in.setGoodsId(insert.getGoodsId());
                if (!Objects.isNull(d.getGallery())) {
                    in.setGallery(JSONObject.toJSONString(d.getGallery()));
                }
                in.setSkuCode(UUID.randomUUID().toString());
                goodsSpecPOList.add(in);
            }
            goodsSpecService.saveBatch(goodsSpecPOList);
            dataSourceTransactionManager.commit(transactionStatus);
            return true;
        } catch (Exception e) {
            dataSourceTransactionManager.rollback(transactionStatus);
            return false;
        }
    }

    /**
     * 获取详情
     *
     * @param goodsId
     * @return
     */
    @Override
    public GoodsDetailVO detail(Integer goodsId) {
        GoodsDetailPO po = goodsMapper.getGoodsDetail(goodsId);
        if (Objects.isNull(po)) {
            throw new ServiceException("找不到资源", 104);
        }
        // 转换
        GoodsDetailVO vo = new GoodsDetailVO();
        BeanUtils.copyProperties(po, vo);
        vo.setGoodsGallery(JSON.parseArray(po.getGoodsGallery()));
        vo.setAttr(po.getAttr().stream().map(p -> {
            GoodsDetailAttrVO v = new GoodsDetailAttrVO();
            BeanUtils.copyProperties(p, v);
            v.setAttrValues(p.getAttrValues().stream().map(pp -> {
                GoodsDetailAttrValueVO vv = new GoodsDetailAttrValueVO();
                BeanUtils.copyProperties(pp, vv);
                return vv;
            }).collect(Collectors.toList()));
            return v;
        }).collect(Collectors.toList()));
        vo.setSpec(po.getSpec().stream().map(p -> {
            GoodsDetailSpecVO v = new GoodsDetailSpecVO();
            BeanUtils.copyProperties(p, v);
            return v;
        }).collect(Collectors.toList()));
        return vo;
    }

    /**
     * 修改
     *
     * @param goodsEditDto
     * @return
     */
    @Override
    public Boolean edit(GoodsEditDTO goodsEditDto) {
        if (goodsEditDto.getSpec().size() == 0) {
            throw new ServiceException("最少填写一个规格", 104);
        }
        GoodsPO data = goodsMapper.selectById(goodsEditDto.getGoodsId());
        if (data == null) {
            throw new ServiceException("找不到资源", 104);
        }
        //开启事务
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        try {
            GoodsPO p = new GoodsPO();
            BeanUtils.copyProperties(goodsEditDto, p);
            if (!Objects.isNull(goodsEditDto.getGoodsGallery())) {
                p.setGoodsGallery(JSONObject.toJSONString(goodsEditDto.getGoodsGallery()));
            }
            // 修改商品信息
            goodsMapper.updateById(p);
            if (!Objects.isNull(goodsEditDto.getAttr())) {
                // 存储属性和属性值
                List<GoodsAttrPO> goodsAttrPOList = new ArrayList<>();
                List<Integer> keepAttrIds = new ArrayList<>();
                for (GoodsEditAttrDTO attr : goodsEditDto.getAttr()) {
                    if (Objects.isNull(attr.getAttrId())) {
                        GoodsAttrPO insertAttr = new GoodsAttrPO();
                        BeanUtils.copyProperties(attr, insertAttr);
                        insertAttr.setGoodsId(goodsEditDto.getGoodsId());
                        goodsAttrPOList.add(insertAttr);
                    } else {
                        keepAttrIds.add(attr.getAttrId());
                        GoodsAttrPO updateAttr = new GoodsAttrPO();
                        BeanUtils.copyProperties(attr, updateAttr);
                        goodsAttrMapper.updateById(updateAttr);
                    }
                }
                // 删除没有传入的属性
                goodsAttrService.remove(new QueryWrapper<GoodsAttrPO>().lambda().eq(GoodsAttrPO::getGoodsId, goodsEditDto.getGoodsId()).notIn(GoodsAttrPO::getAttrId, keepAttrIds));
                // 先把新增的属性加进去
                if (goodsAttrPOList.size() != 0) goodsAttrService.saveBatch(goodsAttrPOList);
                //添加属性值
                List<GoodsAttrValuePO> goodsAttrValuePOList = new ArrayList<>();
                List<Integer> keepAttrValue = new ArrayList<>();
                for (int i = 0; i < goodsEditDto.getAttr().size(); i++) {
                    GoodsEditAttrDTO attr = goodsEditDto.getAttr().get(i);
                    for (GoodsEditAttrValueDTO goodsAttrValue : attr.getAttrValues()) {
                        if (Objects.isNull(goodsAttrValue.getAttrValueId())) {
                            GoodsEditAttrDTO goodsAttr = goodsEditDto.getAttr().get(i);
                            GoodsAttrValuePO insertAttrValue = new GoodsAttrValuePO();
                            BeanUtils.copyProperties(goodsAttrValue, insertAttrValue);
                            insertAttrValue.setGoodsId(goodsEditDto.getGoodsId());
                            insertAttrValue.setAttrId(goodsAttr.getAttrId());
                            goodsAttrValuePOList.add(insertAttrValue);
                        } else {
                            keepAttrValue.add(goodsAttrValue.getAttrValueId());
                            GoodsAttrValuePO updateAttrValue = new GoodsAttrValuePO();
                            BeanUtils.copyProperties(goodsAttrValue, updateAttrValue);
                            goodsAttrValueMapper.updateById(updateAttrValue);
                        }
                    }
                }
                // 删除没有存入的属性值
                goodsAttrValueService.remove(new QueryWrapper<GoodsAttrValuePO>().lambda().eq(GoodsAttrValuePO::getGoodsId, goodsEditDto.getGoodsId()).notIn(GoodsAttrValuePO::getAttrValueId, keepAttrValue));
                // 插入属性值
                if (goodsAttrValuePOList.size() != 0) goodsAttrValueService.saveBatch(goodsAttrValuePOList);
            }
            // 处理规格
            List<GoodsSpecPO> goodsSpecPOList = new ArrayList<>();
            List<Integer> keepSpecIds = new ArrayList<>();
            for (GoodsEditSpecDTO goodsEditSpecDTO : goodsEditDto.getSpec()) {
                // 更新
                if (Objects.isNull(goodsEditSpecDTO.getSpecId())) {
                    // 添加
                    GoodsSpecPO insertGoodsSpecPO = new GoodsSpecPO();
                    BeanUtils.copyProperties(goodsEditSpecDTO, insertGoodsSpecPO);
                    if (!Objects.isNull(goodsEditSpecDTO.getGallery())) {
                        insertGoodsSpecPO.setGallery(JSON.toJSONString(goodsEditSpecDTO.getGallery()));
                    }
                    if (Objects.isNull(goodsEditSpecDTO.getSkuCode())) {
                        insertGoodsSpecPO.setSkuCode(UUID.randomUUID().toString());
                    }
                    insertGoodsSpecPO.setGoodsId(goodsEditDto.getGoodsId());
                    goodsSpecPOList.add(insertGoodsSpecPO);
                } else {
                    keepSpecIds.add(goodsEditSpecDTO.getSpecId());
                    GoodsSpecPO updateGoodsSpecPO = new GoodsSpecPO();
                    BeanUtils.copyProperties(goodsEditSpecDTO, updateGoodsSpecPO);
                    goodsSpecService.updateById(updateGoodsSpecPO);
                }
            }
            // 删除更新中不包含的id
            goodsSpecService.remove(new QueryWrapper<GoodsSpecPO>().lambda().eq(GoodsSpecPO::getGoodsId, goodsEditDto.getGoodsId()).notIn(GoodsSpecPO::getSpecId, keepSpecIds));
            if (goodsSpecPOList.size() != 0) goodsSpecService.saveBatch(goodsSpecPOList);
            // 提交
            dataSourceTransactionManager.commit(transactionStatus);
            return true;
        } catch (Exception e) {
            // 回滚
            dataSourceTransactionManager.rollback(transactionStatus);
            throw new ServiceException(e.getMessage(), 106);
        }
    }

    /**
     * 修改排序
     *
     * @param goodsEditSortDTO
     * @return
     */
    @Override
    public Integer editSort(GoodsEditSortDTO goodsEditSortDTO) {
        GoodsPO po = goodsMapper.selectById(goodsEditSortDTO.getGoodsId());
        if (Objects.isNull(po)) {
            throw new ServiceException("找不到资源", 104);
        }
        GoodsPO p = new GoodsPO();
        BeanUtils.copyProperties(goodsEditSortDTO, p);
        return goodsMapper.updateById(p);
    }

    /**
     * 修改热门状态
     *
     * @param goodsId
     * @return
     */
    @Override
    public Integer editHot(Integer goodsId) {
        GoodsPO po = goodsMapper.selectById(goodsId);
        if (Objects.isNull(po)) {
            throw new ServiceException("找不到资源", 104);
        }
        return goodsMapper.update(null,
                new UpdateWrapper<GoodsPO>().
                        lambda()
                        .eq(GoodsPO::getGoodsId, goodsId)
                        .setSql("is_hot = !is_hot")
        );
    }

    /**
     * 修改新品状态
     *
     * @param goodsId
     * @return
     */
    @Override
    public Integer editNew(Integer goodsId) {
        GoodsPO po = goodsMapper.selectById(goodsId);
        if (Objects.isNull(po)) {
            throw new ServiceException("找不到资源", 104);
        }
        return goodsMapper.update(null,
                new UpdateWrapper<GoodsPO>().
                        lambda()
                        .eq(GoodsPO::getGoodsId, goodsId)
                        .setSql("is_new = !is_new")
        );
    }

    /**
     * 修改显示状态
     *
     * @param goodsId
     * @return
     */
    @Override
    public Integer editShow(Integer goodsId) {
        GoodsPO po = goodsMapper.selectById(goodsId);
        if (Objects.isNull(po)) {
            throw new ServiceException("找不到资源", 104);
        }
        return goodsMapper.update(null,
                new UpdateWrapper<GoodsPO>().
                        lambda()
                        .eq(GoodsPO::getGoodsId, goodsId)
                        .setSql("is_show = !is_show")
        );
    }

    /**
     * 删除商品
     *
     * @param goodsId
     * @return
     */
    @Override
    public Boolean delete(Integer goodsId) {
        // 查询出商品
        GoodsPO po = goodsMapper.selectById(goodsId);
        if (Objects.isNull(po)) {
            throw new ServiceException("找不到资源", 104);
        }
        // 开启事务
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        try {
            // 删除商品
            goodsMapper.delete(new QueryWrapper<GoodsPO>().lambda().eq(GoodsPO::getGoodsId, goodsId));
            //删除属性
            goodsAttrService.remove(new QueryWrapper<GoodsAttrPO>().lambda().eq(GoodsAttrPO::getGoodsId, goodsId));
            //删除属性值
            goodsAttrValueService.remove(new QueryWrapper<GoodsAttrValuePO>().lambda().eq(GoodsAttrValuePO::getGoodsId, goodsId));
            //删除组合
            goodsSpecService.remove(new QueryWrapper<GoodsSpecPO>().lambda().eq(GoodsSpecPO::getGoodsId, goodsId));
            //提交事务
            dataSourceTransactionManager.commit(transactionStatus);
            return true;
        } catch (Exception e) {
            // 回滚
            dataSourceTransactionManager.rollback(transactionStatus);
            throw new ServiceException(e.getMessage(), 106);
        }
    }

    /**
     * 更新库存
     * @param goodsEditStoreCountDTO
     * @return
     */
    @Override
    public Boolean editStoreCount(GoodsEditStoreCountDTO goodsEditStoreCountDTO) {
        GoodsSpecPO goodsSpecPO = goodsSpecService.getOne(new QueryWrapper<GoodsSpecPO>().lambda().eq(GoodsSpecPO::getSpecId, goodsEditStoreCountDTO.getSpecId()));
        if (Objects.isNull(goodsSpecPO)) {
            throw new ServiceException("找不到资源", 104);
        }
        if("add".equals(goodsEditStoreCountDTO.getType().getValue())){
            return goodsSpecService.update(
                    new UpdateWrapper<GoodsSpecPO>()
                            .lambda()
                            .eq(GoodsSpecPO::getSpecId,goodsEditStoreCountDTO.getSpecId())
                            .setSql("store_count = store_count+" +goodsEditStoreCountDTO.getQuantity())
            );
        }else{
            return goodsSpecService.update(
                    new UpdateWrapper<GoodsSpecPO>()
                            .lambda()
                            .eq(GoodsSpecPO::getSpecId,goodsEditStoreCountDTO.getSpecId())
                            .setSql("store_count = store_count-" +goodsEditStoreCountDTO.getQuantity())
            );
        }
    }
}




